home *** CD-ROM | disk | FTP | other *** search
/ CD Exchange / CD Exchange - Volume 1.iso / d.t.p / utils / others / pcal / writefil.c < prev   
C/C++ Source or Header  |  1993-08-12  |  25KB  |  995 lines

  1. /*
  2.  * writefil.c - Pcal routines concerned with writing the PostScript output
  3.  *
  4.  * Contents:
  5.  *
  6.  *        def_footstring
  7.  *        expand_fmt
  8.  *        find_daytext
  9.  *        find_holidays
  10.  *        find_noteboxes
  11.  *        print_db_word
  12.  *        print_julian_info
  13.  *        print_month
  14.  *        print_moon_info
  15.  *        print_dates
  16.  *        print_pstext
  17.  *        print_text
  18.  *        print_word
  19.  *        write_calfile
  20.  *        write_psfile
  21.  *
  22.  * Revision history:
  23.  *
  24.  *    4.3    AWR    12/03/91    add support for -s flag (specify
  25.  *                    alternate date/fill box shading values)
  26.  *
  27.  *    4.2    AWR    10/08/91    add support for -[kK] flags (change
  28.  *                    position of small calendars)
  29.  *
  30.  *            10/03/91    add find_noteboxes(); revise to print
  31.  *                    text in multiple notes boxes
  32.  *
  33.  *                    add support for -S flag
  34.  *
  35.  *            10/02/91    modify def_footstring() to handle all
  36.  *                    types of strings; use it to print notes
  37.  *                    header (-N flag)
  38.  *
  39.  *            09/19/91    add write_calfile(), print_dates(),
  40.  *                    and new print_text() to generate 
  41.  *                    input for Un*x "calendar" utility;
  42.  *                    renamed old print_text() as
  43.  *                    print_pstext() for clarity; revised
  44.  *                    to simplify setting working date
  45.  *
  46.  *    4.11    AWR    08/23/91    revise expand_fmt() to write results
  47.  *                    to string instead of stdout; revise
  48.  *                    print_word() to avoid writing null
  49.  *                    strings
  50.  *
  51.  *        AWR    08/21/91    use ABBR_DAY_LEN and ABBR_MONTH_LEN
  52.  *                    (cf. pcallang.h) to print abbreviated
  53.  *                    day/month names
  54.  *
  55.  *        AWR    08/21/91    add %u and %w (calculate week number
  56.  *                    so that 1/1 is always week 1); support
  57.  *                    %[+-]<n>[DWMY] to adjust working date
  58.  *                    by +|- <n> days/weeks/months/years
  59.  *
  60.  *    4.1    AWR    08/16/91    Support -G flag (outlined gray dates)
  61.  *
  62.  *    4.02    AWR    07/02/91    Added "%" expansions in text strings
  63.  *                    (cf. expand_fmt())
  64.  *
  65.  *    4.0    AWR    01/28/91    Support -B, -w flags and moon file
  66.  *
  67.  *            01/15/91    Extracted from pcal.c
  68.  *
  69.  */
  70.  
  71. /*
  72.  * Standard headers:
  73.  */
  74.  
  75. #include <stdio.h>
  76. #include <ctype.h>
  77. #include <string.h>
  78.  
  79. /*
  80.  * Pcal-specific definitions:
  81.  */
  82.  
  83. #include "pcaldefs.h"
  84. #include "pcalglob.h"
  85. #define  WRITEFIL        /* to get ordinal_suffix() from pcallang.h */
  86. #include "pcallang.h"
  87. #include "pcalinit.h"        /* PostScript boilerplate */
  88.  
  89. /*
  90.  * Macros:
  91.  */
  92.  
  93. /* make sure PRT() doesn't round "ph" up to 1.0 when printing it */
  94. #define PRT_TWEAK(ph)        ((ph) >= 0.9995 ? 0.0 : (ph))
  95.  
  96. /* advance working date by n days */
  97. #define SET_DATE(n)    do {                        \
  98.     MAKE_DATE(date, work_month, work_day + (n), work_year);        \
  99.     normalize(&date);                        \
  100.     work_month = date.mm, work_day = date.dd, work_year = date.yy;    \
  101. } while (0)
  102.  
  103. /* reset working date to original date */
  104. #define RESET_DATE    \
  105. work_month = this_month, work_day = this_day, work_year = this_year
  106.  
  107. /*
  108.  * Globals:
  109.  */
  110.  
  111. /* order of following strings must conform to #define's in pcaldefs.h (q.v.) */
  112. static char *cond[3] = {"false", "true", "(some)"};
  113. static char *gray[3] = {"(gray)", "(outline)", "(outline_gray)"};
  114.  
  115. static int this_day, this_month, this_year;    /* current day */
  116. static int work_day, work_month, work_year;    /* working day (cf. expand_fmt()) */
  117. static char *kw_note, *kw_opt, *kw_year;    /* keywords for -c output */
  118.  
  119. static int debug_text;                /* generate debug output */
  120.  
  121.  
  122. /*
  123.  * write_psfile - write PostScript code
  124.  *
  125.  * The actual output of the PostScript code is straightforward.  This routine
  126.  * writes a PostScript header followed by declarations of all the PostScript
  127.  * variables affected by command-line flags and/or language dependencies.  It
  128.  * the generates the PostScript boilerplate generated from pcalinit.ps, and
  129.  * finally calls print_month() to generate the PostScript code for each
  130.  * requested month.
  131.  */
  132. #ifdef PROTOS
  133. void write_psfile(int month,
  134.           int year,
  135.           int nmonths)
  136. #else
  137. void write_psfile(month, year, nmonths)
  138.     int month;            /* starting month   */
  139.     int year;            /* starting year    */
  140.     int nmonths;            /* number of months */
  141. #endif
  142. {
  143.     int i, ngray, nfsize;
  144.     char *p, **ap, tmp[STRSIZ];
  145.  
  146.     debug_text = DEBUG(DEBUG_TEXT);        /* debug text output? */
  147.  
  148.     /*
  149.      * Write out PostScript prolog
  150.      */
  151.  
  152.      PRT("%%!PS-Adobe-1.0\n%%\t");
  153.     PRT(VERSION_MSG, progname, version);
  154.     if (*datefile)
  155.         PRT(DATEFILE_MSG, datefile);
  156.     PRT("\n%%\n");
  157.  
  158.     /* font names and sizes (notes font only in 4.2) */
  159.  
  160.     nfsize = (p = strrchr(notesfont, '/')) ? *p = '\0', atoi(p + 1) :
  161.                 atoi(strrchr(NOTESFONT, '/') + 1);
  162.  
  163.     PRT("/titlefont /%s def\n/dayfont /%s def\n/notesfont /%s def\n",
  164.         titlefont, dayfont, notesfont);
  165.     PRT("/notesfontsize %d def\n", nfsize);
  166.  
  167.     /* month names */
  168.  
  169.     PRT("/month_names [");
  170.     for (i = JAN; i <= DEC; i++) {
  171.         PRT(i % 6 == 1 ? "\n\t" : " ");
  172.         (void) print_word(months[i-1]);
  173.     }
  174.     PRT(" ] def\n");
  175.  
  176.     /* day names - abbreviate if printing entire year on page */
  177.  
  178.     PRT("/day_names [");
  179.     for (i = SUN; i <= SAT; i++) {
  180.         PRT(i % 6 == 0 && ! do_whole_year ? "\n\t" : " ");
  181.         strcpy(tmp, days[(i + first_day_of_week) % 7]);
  182.         if (do_whole_year)
  183.             tmp[ABBR_DAY_LEN] = '\0';
  184.         (void) print_word(tmp);
  185.         }
  186.     PRT(" ] def\n");
  187.  
  188.     /* line separator */
  189.  
  190.     PRT("/linesep ");
  191.     print_word(LINE_SEP);
  192.     PRT(" def\n");
  193.  
  194.     /* colors (black/gray) to print weekdays and holidays */
  195.  
  196.     PRT("/day_gray [");
  197.     for (ngray = 0, i = SUN; i <= SAT; ngray += day_color[i++] == GRAY)
  198.         PRT(" %s", cond[day_color[(i + first_day_of_week) % 7]]);
  199.     PRT(" ] def\n");
  200.     PRT("/holiday_gray %s def\n", cond[ngray <= 3]);
  201.     PRT("/logical_gray %s def\n", gray[num_style]);
  202.  
  203.      /* rotation, scale, and translate values */
  204.  
  205.      PRT("/rval %d def\n", rotate);
  206.      PRT("/xsval %s def\n/ysval %s def\n", xsval, ysval);
  207.      PRT("/xtval %s def\n/ytval %s def\n", xtval, ytval);
  208.  
  209.     /* moon, Julian date, and box fill flags */
  210.  
  211.     PRT("/draw-moons %s def\n", cond[draw_moons]);
  212.     PRT("/julian-dates %s def\n", cond[julian_dates]);
  213.     PRT("/fill-boxes %s def\n", cond[! blank_boxes]);
  214.  
  215.     /* position of small calendars */
  216.  
  217.     PRT("/prev_small_cal %d def\n", prev_cal_box[small_cal_pos]);
  218.     PRT("/next_small_cal %d def\n", next_cal_box[small_cal_pos]);
  219.  
  220.     /* date and fill box shading values */
  221.  
  222.     strcpy(tmp, shading);
  223.     *(p = strchr(tmp, '/')) = '\0';
  224.     PRT("/dategray %s def\n", tmp);
  225.     PRT("/fillgray %s def\n", p + 1);
  226.  
  227.     /* PostScript boilerplate (part 1 of 1) */
  228.  
  229.     for (ap = header; *ap; ap++)
  230.         PRT("%s\n", *ap);
  231.     PRT("\n");
  232.  
  233.     /*
  234.      * Write out PostScript code to print calendars
  235.      */
  236.  
  237.     for (this_month = month, this_year = year; nmonths--; ) {
  238.         print_month(this_month, this_year);
  239.         this_year = NEXT_YEAR(this_month, this_year);
  240.         this_month = NEXT_MONTH(this_month, this_year);
  241.     }
  242.  
  243. }
  244.  
  245.  
  246. /*
  247.  * write_calfile - write dates in format suitable for Un*x "calendar" utility
  248.  * (and subsequent use by Pcal)
  249.  */
  250. #ifdef PROTOS
  251. void write_calfile(int month,
  252.            int year,
  253.            int nmonths)
  254. #else
  255. void write_calfile(month, year, nmonths)
  256.     int month;            /* starting month   */
  257.     int year;            /* starting year    */
  258.     int nmonths;            /* number of months */
  259. #endif
  260. {
  261.     KWD *k;
  262.  
  263.     /* look up the Pcal keywords (assumed present) for the -c output file */
  264.     for (k = keywds; k->name; k++) {
  265.         if (k->code == DT_NOTE) kw_note = k->name;
  266.         if (k->code == DT_OPT)  kw_opt  = k->name;
  267.         if (k->code == DT_YEAR) kw_year = k->name;
  268.     }
  269.  
  270.     /* print the date style for subsequent use by Pcal */
  271.     PRT("%s -%c\n", kw_opt, date_style == USA_DATES ? F_USA_DATES :
  272.                               F_EUR_DATES);
  273.  
  274.     for (this_month = month, this_year = year; nmonths--; ) {
  275.         print_dates(this_month, this_year);
  276.         this_year = NEXT_YEAR(this_month, this_year);
  277.         this_month = NEXT_MONTH(this_month, this_year);
  278.     }
  279. }
  280.  
  281. /*
  282.  * low-level utilities for PostScript generation
  283.  */
  284.  
  285. /*
  286.  * expand_fmt - expand a strftime-like date format specifier; pcal supports
  287.  * %[aAbBdjmUWyY] from strftime() plus %[luwDM] and prefixes [0o+-] (see below);
  288.  * places expanded string in output buffer and returns pointer to character
  289.  * following end of format specifier.  Assumes working date has been initialized
  290.  * (via RESET_DATE macro) prior to first call for a given text string
  291.  */
  292. #ifdef PROTOS
  293. char *expand_fmt(char *buf,
  294.          char *p)
  295. #else
  296. char *expand_fmt(buf, p)
  297.     char *buf;        /* output buffer (filled in)        */
  298.     char *p;        /* character following percent sign */
  299. #endif
  300. {
  301.     char c;
  302.     static char *prefixes = "0o+-";
  303.     int firstday, wkday;
  304.     int adjust = 0, print_lz = FALSE, ordinal = FALSE, prev_num = -1;
  305.     int num_present = FALSE, num_value = 0;
  306.     DATE date;
  307.  
  308.     /* For